﻿using CoreDomain;
using DomainService.IService;
using Infrastructure;
using Infrastructure.IRepository;
using Infrastructure.Repository;
using Model.BusinessModel.InPut;
using Model.BusinessModel.OutPut;
using Model.DomainModel;
using Model.Flow;
using Model.OverallAtuhModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Utility;
using Utility.Enum;

namespace DomainService.Service
{
    /// <summary>
    /// 流程信息服务接口实现
    /// </summary>
    public class FlowMessageService : IFlowMessageService
    {
        #region 构造实列化

        /// <summary>
        /// 流程消息仓储接口
        /// </summary>
        private readonly IFlowMessageRepository _flowMessageRepository;

        /// <summary>
        /// 流程节点配置仓储接口
        /// </summary>
        private readonly IFlowNodeConfigRepository _flowNodeConfigRepository;

        /// <summary>
        /// 流程审批记录仓储接口
        /// </summary>
        private readonly IFlowApplyRecordRepository _flowApplyRecordRepository;

        /// <summary>
        /// 流程审批仓储接口
        /// </summary>
        private readonly IFlowApplyRepository _flowApplyRepository;

        /// <summary>
        /// 流程审批服务
        /// </summary>
        private readonly IFlowApplyService _flowApplyService;

        /// <summary>
        /// 基础服务
        /// </summary>
        private readonly IBaseService _baseService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="flowMessageRepository"></param>
        /// <param name="flowNodeConfigRepository"></param>
        /// <param name="flowApplyRecordRepository"></param>
        /// <param name="baseService"></param>
        public FlowMessageService(IFlowMessageRepository flowMessageRepository, IFlowNodeConfigRepository flowNodeConfigRepository, IFlowApplyRecordRepository flowApplyRecordRepository, IBaseService baseService, IFlowApplyService flowApplyService, IFlowApplyRepository flowApplyRepository)
        {
            _flowMessageRepository = flowMessageRepository;
            _flowNodeConfigRepository = flowNodeConfigRepository;
            _flowApplyRecordRepository = flowApplyRecordRepository;
            _baseService = baseService;
            _flowApplyService = flowApplyService;
            _flowApplyRepository = flowApplyRepository;
        }

        #endregion

        #region  接口实现

        /// <summary>
        /// 检测即将过期或过期流程节点,并写入数据库
        /// </summary>
        public ReceiveStatus CheckExpireFlowNode()
        {
            ReceiveStatus receiveStatus = new();
            List<FlowMessage> flowMessages = new List<FlowMessage>();
            //获取存在过期配置的数据
            var expireConfigList = _flowNodeConfigRepository.GetExpireConfig(true);
            var currentTime = DateTime.Now;
            var isRecordMsg = true;
            foreach (var expireConfig in expireConfigList)
            {
                //验证当前流程节点是否还未审核
                var applyRecordModel = _flowApplyRecordRepository.GetFlowApplyRecordByNodeId(expireConfig.FlowNodeId, expireConfig.FlowApplyId).FirstOrDefault();
                if (applyRecordModel != null && (applyRecordModel.NodeExamineState != (int)FlowNodeStateEnum.InExamine || applyRecordModel.NodeExamineState != (int)FlowNodeStateEnum.AuditDismissal && expireConfig.CurrentNodeReviewerId.Contains(applyRecordModel.NodeReviewerId)))
                    continue;

                //获取对应流程节点消息数据
                var flowMessageList = _flowMessageRepository.GetFlowMessageData(expireConfig.FlowApplyId, expireConfig.FlowNodeId);

                //过期配置
                var expireDateModel = JsonHelper.JsonStrToEntity<ExpireDateModel>(expireConfig.ExpireConfig);

                //是否过期提醒
                if (!expireDateModel.IsExpireRemind)
                    continue;

                //计算是否过期
                var expireConfigTime = DateTime.Now;
                if (expireDateModel.ExpireType == (int)ExpireTypeEnum.Day)
                    expireConfigTime = expireConfig.CurrentNodeUpdateTime.AddDays(expireDateModel.ExpireDate);
                else
                    expireConfigTime = expireConfig.CurrentNodeUpdateTime.AddHours(expireDateModel.ExpireDate);

                //如果过期配置时间小于等于当前时间,说明超过了过期时间还未审核,那么要发出已过期消息
                if (expireConfigTime <= currentTime)
                {
                    var isTrue = flowMessageList.Any(f => f.MessageState == (int)MessageStateEnum.Expired && expireConfig.CurrentNodeReviewerId.Contains(f.MessageRecipient) && f.IsHandled == false);
                    if (!isTrue)
                    {
                        var msgList = FlowMessageCore.SetFlowMessage(expireConfig, expireDateModel, MessageStateEnum.Expired);
                        var applyInput = FlowMessageCore.MessageHandled(expireDateModel.ExpireAction, msgList[0], expireConfig); //当一个节点可以多个人审批，那么只去一条
                        if (!string.IsNullOrWhiteSpace(applyInput.FlowApplyId))
                        {
                            var result = _flowApplyService.FlowApplyExamine(applyInput, FlowMessageCore.GetLoginOutPut(msgList[0].MessageRecipient, expireConfig.CurrentNodeReviewerName.Split(',')[0]));
                            if (!result.success)
                                isRecordMsg = false;
                        }
                        flowMessages.AddRange(msgList);
                    }

                }
                //如果过期配置时间减当前时间，小于提前通知时间，那么要发送一个即将过期提醒消息
                if ((expireConfigTime - currentTime).TotalMinutes <= expireDateModel.SoonExpireDate)
                {
                    var isTrue = flowMessageList.Any(f => f.MessageState == (int)MessageStateEnum.SoonExpire && expireConfig.CurrentNodeReviewerId.Contains(f.MessageRecipient) && f.IsHandled == false);
                    if (!isTrue)
                        flowMessages.AddRange(FlowMessageCore.SetFlowMessage(expireConfig, expireDateModel, MessageStateEnum.SoonExpire));
                }
            }
            //写入数据库
            TransactionHelper.ExecuteTransaction(() =>
            {
                if (flowMessages.Count > 0 && isRecordMsg)
                {
                    foreach (var item in flowMessages)
                    {
                        if (item.IsHandled)
                            _flowMessageRepository.UpdateFlowMessage(item);
                    }
                    _flowMessageRepository.BulkInsert(flowMessages);
                }
            });
            return receiveStatus;
        }

        /// <summary>
        /// 新增流程消息
        /// </summary>
        /// <param name="flowApplyId">流程申请id</param>
        /// <param name="recipientKeys">接收人员key</param>
        /// <param name="messageType">消息类型</param>
        /// <returns></returns>
        public ReceiveStatus Insert(string flowApplyId, string recipientKeys, MessageTypeEnum messageType)
        {
            ReceiveStatus receiveStatus = new ReceiveStatus();
            if (string.IsNullOrWhiteSpace(flowApplyId))
                return ExceptionHelper.CustomException("请选择抄送流程");
            if (string.IsNullOrWhiteSpace(recipientKeys))
                return ExceptionHelper.CustomException("请选择抄送人！");
            var messageRecipientList = recipientKeys.Split(',').ToList();
            //验证申请是否存在
            var model = _flowApplyRepository.GetByKey(flowApplyId, BaseSqlRepository.flowApply_selectByKeySql);
            if (model == null)
                return ExceptionHelper.CustomException("该申请不存在，审核失败！");

            var loginResult = _baseService.GetUserInfo();
            if (loginResult == null)
                return ExceptionHelper.CustomException("不存在登录信息，请重新登录！");

            //不能推送给自己
            if (messageRecipientList.Any(f => f == loginResult.UserId))
                return ExceptionHelper.CustomException("不能抄送给自己");
            //获取用户
            var userList = MemoryCacheHelper.GetCachedDataByKey<List<SysUser>>(ConstHelper.UserCacheKey);
            if (userList.success == false)
                ExceptionHelper.ThrowBusinessException("用户缓存不存在或已过期,请重置缓存");

            //验证消息是否发送

            var messageList = _flowMessageRepository.GetCarbonCopyFlowMessage(flowApplyId, messageRecipientList, loginResult.UserId, messageType);

            List<FlowMessage> carbonCopyList = new List<FlowMessage>();
            if (messageList.Count == 0)
            {
                foreach (var item in messageRecipientList)
                {
                    FlowMessage carbonCopyMsg = new()
                    {
                        MessageId = Guid.NewGuid().ToString(),
                        MessageTitle = model.ApplyTitle,
                        NodeName = model.CurrentNodeName ?? string.Empty,
                        NodeId = model.CurrentNodeId ?? string.Empty,
                        MessageRecipient = item,
                        MessageContent = "该流程消息为，推送给抄送人",
                        FlowApplyId = flowApplyId,
                        MessageType = (int)MessageTypeEnum.CarbonCopy,
                        MessageState = (int)MessageStateEnum.Normal,
                        IsBrowse = false,
                        BrowseTime = null,
                        IsHandled = true,
                        HandledTime = DateTime.Now,
                        HandledType = (int)ExpireActionEnum.Normal,
                        HandledState = model.CurrentNodeState,
                        MessageSender = loginResult.UserId,
                        CreateTime = DateTime.Now,
                        CreateUserKey = loginResult.UserId,
                    };
                    carbonCopyList.Add(carbonCopyMsg);
                }
            }
            else
            {
                foreach (FlowMessage message in messageList)
                {
                    var userModel = userList?.data?.Where(f => f.UserId == message.MessageRecipient).FirstOrDefault();
                    if (userModel != null)
                    {
                        return ExceptionHelper<List<FlowMessage>>.CustomExceptionData($"该流程已抄送给【{userModel.UserName}】,请重新选择");
                    }

                }
            }

            //写入数据库
            TransactionHelper.ExecuteTransaction(() =>
            {
                //把流程推送给抄送人
                if (carbonCopyList.Count > 0)
                    _flowMessageRepository.BulkInsert(carbonCopyList);
            });

            return receiveStatus;
        }

        /// <summary>
        /// 获取当前登录人员流程信息
        /// </summary>
        /// <returns></returns>
        public ReceiveStatus<List<FlowMessage>> GetFlowMessage()
        {
            ReceiveStatus<List<FlowMessage>> receiveStatus = new ReceiveStatus<List<FlowMessage>>();
            var loginResult = _baseService.GetUserInfo();
            if (loginResult == null)
                return ExceptionHelper<List<FlowMessage>>.CustomExceptionData("不存在登录信息，请重新登录！");
            var flowMessageList = _flowMessageRepository.GetFlowMessageByUserId(loginResult.UserId);

            receiveStatus.data = flowMessageList;
            return receiveStatus;
        }

        #endregion
    }
}
